package com.tangx.comment.service.impl;

import com.tangx.apis.user.IUserClient;
import com.tangx.comment.service.ApCommentHotService;
import com.tangx.comment.service.CommentService;
import com.tangx.model.comment.dtos.CommentDto;
import com.tangx.model.comment.dtos.CommentLikeDto;
import com.tangx.model.comment.dtos.CommentSaveDto;
import com.tangx.model.comment.pojos.ApComment;
import com.tangx.model.comment.pojos.ApCommentLike;
import com.tangx.model.comment.vos.CommentVo;
import com.tangx.model.common.dtos.ResponseResult;
import com.tangx.model.common.enums.AppHttpCodeEnum;
import com.tangx.model.user.pojos.ApUser;
import com.tangx.utils.common.ThreadLocalUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private IUserClient userClient;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public ResponseResult save(CommentSaveDto dto) {
        //1.判断用户是否登录
        Integer userId = ThreadLocalUtil.getUserId();
        if(userId==null || userId==0){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //2.判断用户是否存在
        ApUser apUser = userClient.findById(userId);
        if(apUser==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户不存在");
        }

        //TODO 3.判断文章是否存在

        //4.判断评论内容是否超140字
        if(dto.getContent().length()>140){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "评论内容超140字不能评论");
        }

        //TODO 5.评论内容安全过滤（DFA检测+阿里云文本审核）

        //6.构建评论数据保存到Mongo中
        ApComment apComment = new ApComment();
        apComment.setUserId(userId);//评论用户ID
        apComment.setUserName(apUser.getName());//评论用户名称
        apComment.setImage(apUser.getImage());//评论用户头像
        apComment.setObjectId(dto.getArticleId());//文章ID
        apComment.setType(0);//类型-文章
        apComment.setContent(dto.getContent());//评论用户内容
        apComment.setFlag(0);//普通评论
        apComment.setLikes(0);//点赞数量
        apComment.setReply(0);//回复数量
        apComment.setCreatedTime(new Date());//创建时间
        apComment.setUpdatedTime(new Date());//更新时间

        mongoTemplate.save(apComment);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Autowired
    private ApCommentHotService apCommentHotService;


    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //1.判断用户是否登录
        Integer userId = ThreadLocalUtil.getUserId();
        if(userId==null || userId==0){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //2.查询用户是否存在
        ApUser apUser = userClient.findById(userId);
        if(apUser==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户不存在");
        }

        //3.判断评论是否存在
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if(apComment==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "评论不存在");
        }

        //4.查询点赞记录
        ApCommentLike apCommentLike = mongoTemplate.findOne(Query.query(
                Criteria.where("userId").is(userId)
                        .and("commentId")
                        .is(dto.getCommentId())),
                ApCommentLike.class);

        //5.如果点赞记录不存在
        if(apCommentLike==null){
            //5.1 如果是取消点赞，响应错误码
            if(dto.getOperation()==1){
                return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "点赞记录不存在无法取消点赞");
            }

            //5.2 如果是点赞，更新评论集合里点赞数+1，保存点赞记录到点赞记录集合中
            mongoTemplate.findAndModify(Query.query(
                    Criteria.where("id").is(dto.getCommentId())),
                    new Update().inc("likes",1),
                    ApComment.class);

            apCommentLike = new ApCommentLike();
            apCommentLike.setCommentId(dto.getCommentId());//评论ID
            apCommentLike.setUserId(userId);//点赞用户ID
            apCommentLike.setOperation(dto.getOperation());//操作类型 0-点赞 1-取消点赞
            mongoTemplate.save(apCommentLike);

        } else {
            //6.如果点赞记录存在
            if(dto.getOperation()==0 && apCommentLike.getOperation()==0){
                return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "无需重复点赞");
            }

            if(dto.getOperation()==1 && apCommentLike.getOperation()==1){
                return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "无需重复取消点赞");
            }


            //判断如果是点赞，则将点赞数+1
            if(dto.getOperation()==0){
                mongoTemplate.findAndModify(Query.query(
                        Criteria.where("id").is(dto.getCommentId())),
                        new Update().inc("likes",1),
                        ApComment.class);
            } else { //如果是取消点赞，则将点赞数-1
                mongoTemplate.findAndModify(Query.query(
                        Criteria.where("id").is(dto.getCommentId())),
                        new Update().inc("likes",-1),
                        ApComment.class);
            }

            //更新点赞记录
            apCommentLike.setOperation(dto.getOperation());
            mongoTemplate.save(apCommentLike);
        }

        //7.查询最新点赞数并返回
        apComment = mongoTemplate.findById(dto.getCommentId(),ApComment.class);
        Map map = new HashMap<>();
        map.put("likes", apComment.getLikes());

        //当前评论是普通评论且点赞数超过5，那么就提交异步计算热点评论的任务
        if(dto.getOperation()==0){
            if(apComment.getFlag()==0 && apComment.getLikes()>5){
                apCommentHotService.computeHotComment(apComment);
            }
        }
        return ResponseResult.okResult(map);
    }


    @Override
    public ResponseResult load(CommentDto dto) {
        //1.查询评论列表
        int size = 10;

        List<ApComment> apCommentList = new ArrayList<>();

        //如果来自于首页请求，查询热点评论列表+普通普通评论列表
        if(dto.getIndex()==1){
            //查询热点评论列表（查询条件：文章ID、类型、创建时间、flag  结果：点赞数倒排序 限制5条）
           List<ApComment> apCommentHotList = mongoTemplate.find(Query.query(Criteria.where("objectId").is(dto.getArticleId())
                            .and("type").is(0)
                            .and("createdTime").lt(dto.getMinDate())
                            .and("flag").is(1)//热点评论
                    ).with(Sort.by(Sort.Direction.DESC, "likes")).limit(5),
                    ApComment.class);

            apCommentList.addAll(apCommentHotList); //将热点评论列表添加到最终的评论列表中

            //查询普通评论列表（查询条件：文章ID、类型、创建时间、flag  结果：创建时间倒排序 限制条数=size-apCommentHotList.size()）
            List<ApComment> apCommentCommonList = mongoTemplate.find(Query.query(Criteria.where("objectId").is(dto.getArticleId())
                            .and("type").is(0)
                            .and("createdTime").lt(dto.getMinDate())
                            .and("flag").is(0)//普通评论
                    ).with(Sort.by(Sort.Direction.DESC, "createdTime")).limit(size-apCommentHotList.size()),
                    ApComment.class);
            apCommentList.addAll(apCommentCommonList);//将普通评论列表添加到最终的评论列表中

        } else { //如果来自于非首页请求，只查询普通评论列表（查询条件：文章ID、类型、创建时间、flag  结果：创建时间倒排序 限制10条）
            apCommentList = mongoTemplate.find(Query.query(Criteria.where("objectId").is(dto.getArticleId())
                            .and("type").is(0)
                            .and("createdTime").lt(dto.getMinDate())
                            .and("flag").is(0)//普通评论
                    ).with(Sort.by(Sort.Direction.DESC, "createdTime")).limit(size),
                    ApComment.class);
        }


        Integer userId = ThreadLocalUtil.getUserId();

        //2.判断用户如果未登录，直接响应评论列表
        if(userId==null || userId==0){
            return ResponseResult.okResult(apCommentList);
        }

        //3.如果用户已登录，需要获取评论的点赞情况（哪些评论是当前登录用户点赞过的）

        //获取评论ID列表
        List<String> commentIdList = apCommentList.stream().map(ApComment::getId).collect(Collectors.toList());

        //查询点赞记录集合里的数据（条件：评论ID列表、用户ID、operation ）
        List<ApCommentLike> apCommentLikeList = mongoTemplate.find(Query.query(Criteria
                .where("commentId").in(commentIdList)
                .and("userId").is(userId)
                .and("operation").is(0) //点赞的数据
        ), ApCommentLike.class);

        List<CommentVo> commentVoList = new ArrayList<>();
        for (ApComment apComment : apCommentList) {

            //带标识的评论数据
            CommentVo commentVo = new CommentVo();
            BeanUtils.copyProperties(apComment,commentVo);

            for (ApCommentLike apCommentLike : apCommentLikeList) {

                //找到被当前登录用户点赞过的评论，并标识评论为已点赞
                if(apCommentLike.getCommentId().equals(apComment.getId())){
                    commentVo.setOperation(0);
                    break;
                }
            }

            commentVoList.add(commentVo);
        }

        return ResponseResult.okResult(commentVoList);
    }
}
